package com.example.apidocserver.domain.document.event.impl;

import com.example.apidocserver.application.dto.UserDocInfoDto;
import com.example.apidocserver.domain.document.entity.ApiInfo;
import com.example.apidocserver.domain.document.event.ApiInfoDomainEvent;
import com.example.apidocserver.domain.document.event.FieldParamDomainEvent;
import com.example.apidocserver.domain.document.event.ParamHisDomainEvent;
import com.example.apidocserver.domain.document.service.ApiInfoService;
import com.example.apidocserver.domain.user.entity.DocUsrHis;
import com.example.apidocserver.infrastructure.util.entity.ApiInfoUtil;
import com.example.apidocserver.infrastructure.util.result.ParamException;
import com.example.apidocserver.infrastructure.util.user.UserDocAuthUtil;
import com.example.apidocserver.interfaces.vo.ApiInfoAllVo;
import com.example.apidocserver.interfaces.vo.DocumentVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Set;

import static com.example.apidocserver.infrastructure.constants.SystemConstants.*;

/**
 * 接口领域驱动
 *
 * @author xyqlg
 */
@Service
@Slf4j
public class ApiInfoDomainEventImpl implements ApiInfoDomainEvent {
    @Resource
    private ApiInfoService apiInfoService;

    @Resource
    private FieldParamDomainEvent fieldParamDomainEvent;

    @Resource
    private ParamHisDomainEvent paramHisDomainEvent;

    @Override
    public ApiInfo queryById(Integer apiId) {
        return apiInfoService.queryById(apiId);
    }

    @Override
    public void setApiInfoAllByUser(DocumentVo documentVo, DocUsrHis docUsrHis) {
        // 0.设置返回参数
        UserDocInfoDto userDocInfoDto = UserDocAuthUtil.currentDocInfo();
        ApiInfoAllVo apiInfoAllVo = new ApiInfoAllVo().setUpdateFlag(userDocInfoDto.isUpdateApiFlag());
        documentVo.setCurrentApiInfo(apiInfoAllVo);

        // 1.接口是否操作
        boolean apiInfoExists = findApiInfo(documentVo, docUsrHis, apiInfoAllVo);
        if (!apiInfoExists) {
            return;
        }

        // 2.设置参数说明、字段说明
        fieldParamDomainEvent.setParamDesc(apiInfoAllVo);

        // 3.设置接口示例
        paramHisDomainEvent.setParamHis(docUsrHis, apiInfoAllVo);
    }

    private boolean findApiInfo(DocumentVo documentVo, DocUsrHis docUsrHis, ApiInfoAllVo apiInfoAllVo) {
        // 1.判断是存在接口文档
        Set<Integer> apiIdSet = documentVo.getApiIdSet();
        if (CollectionUtils.isEmpty(apiIdSet)) {
            // 文档中不包含id则不存在api
            return false;
        }
        if (Objects.isNull(docUsrHis.getApiId()) || !apiIdSet.contains(docUsrHis.getApiId())) {
            // 历史apiId不存在或者文档中不包含该api则查询设置
            docUsrHis.setApiId(apiIdSet.stream().findFirst().get());
        }

        ApiInfo apiInfo  = apiInfoService.queryById(docUsrHis.getApiId());
        // 接口对象操作 且 只读时要启用
        UserDocInfoDto userDocInfoDto = UserDocAuthUtil.currentDocInfo();

        boolean exists = !Objects.isNull(apiInfo) && (userDocInfoDto.isWriteFlag() || apiInfo.getEnableFlag() == 1);
        if (!exists) {
            Integer id = documentVo.getCurrentDocument().getId();
            if (Objects.isNull(id)) {
                // 文档信息不存在
                documentVo.setCurrentApiInfo(ApiInfoUtil.getDefVo());
                return false;
            } else {
                apiInfo = apiInfoService.getDefApiInfo(id);
                if (Objects.isNull(apiInfo)) {
                    // 如果没有接口则返回默认信息
                    documentVo.setCurrentApiInfo(ApiInfoUtil.getDefVo());
                    return false;
                } else {
                    apiInfoAllVo.setApiInfo(apiInfo);
                }
            }
        } else {
            apiInfoAllVo.setApiInfo(apiInfo);
        }
        docUsrHis.setApiId(apiInfo.getId());
        return true;
    }

    @Override
    public ApiInfoAllVo getApiInfoAll(Integer apiId, DocUsrHis docUsrHis) {
        // 1.查询接口信息
        ApiInfo apiInfo = apiInfoService.queryById(apiId);
        if (Objects.isNull(apiInfo)) {
            throw new ParamException("数据不存在。");
        }
        ApiInfoAllVo apiInfoVoResult = new ApiInfoAllVo().setApiInfo(apiInfo);

        // 2.设置参数说明、字段说明
        fieldParamDomainEvent.setParamDesc(apiInfoVoResult);

        // 3.设置接口示例
        paramHisDomainEvent.setParamHis(docUsrHis, apiInfoVoResult);
        return apiInfoVoResult;
    }

    @Override
    public ApiInfo upsertApiInfo(ApiInfo apiInfoIn) {
        log.info("增加或修改接口信息");
        if (Objects.isNull(apiInfoIn)) {
            throw new ParamException("接口数据为空。");
        }

        Date now = new Date();
        if (Objects.isNull(apiInfoIn.getId())) {
            // 新增接口信息
            apiInfoIn.setEnableFlag(YES).setApiHeader(HTTP_DEF_HEADER).setStateId(FT_STR)
                    .setCreateTime(now).setUpdateTime(now);
            return apiInfoService.insert(apiInfoIn);
        } else {
            // 修改接口
            apiInfoIn.setSpaceId(null).setUpdateTime(now);
            log.info("更新接口信息");
            return apiInfoService.update(apiInfoIn);
        }
    }

    @Override
    public List<ApiInfo> findApiLike(ApiInfo apiInfo, Integer docId) {
        return apiInfoService.findApiLike(apiInfo, docId);
    }

    @Override
    public List<ApiInfo> findAllBySpaceId(Integer spaceId) {
        return apiInfoService.findAllBySpaceId(spaceId);
    }

    @Override
    public void insertOrFindBatch(List<ApiInfo> apiInfoList) {
        apiInfoService.insertOrFindBatch(apiInfoList);
    }
}
